import socket
import threading
import time
from typing import Optional, Dict, Any
import sys
import os

# 添加父目录到路径以导入server模块
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from src.server.protocol import Protocol, MessageType

class DatabaseClient:
    """数据库客户端"""
    
    def __init__(self, host: str = "localhost", port: int = 8888):
        self.host = host
        self.port = port
        self.socket = None
        self.connected = False
        self.session_id = None
        self.user_info = None
        self.running = False
        
    def connect(self) -> bool:
        """连接到服务器"""
        try:
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.socket.connect((self.host, self.port))
            self.connected = True
            self.running = True
            
            # 启动接收线程
            receive_thread = threading.Thread(target=self._receive_messages)
            receive_thread.daemon = True
            receive_thread.start()
            
            print(f"已连接到数据库服务器 {self.host}:{self.port}")
            return True
        except Exception as e:
            print(f"连接失败: {e}")
            return False
    
    def disconnect(self):
        """断开连接"""
        self.running = False
        self.connected = False
        if self.socket:
            self.socket.close()
        print("已断开连接")
    
    def login(self, username: str, password: str) -> bool:
        """用户登录"""
        if not self.connected:
            print("请先连接到服务器")
            return False
        
        try:
            message = Protocol.create_login_request(username, password)
            self.socket.send(message)
            
            # 等待登录响应（简单实现，实际应该用事件或回调）
            time.sleep(0.5)
            return self.session_id is not None
        except Exception as e:
            print(f"登录失败: {e}")
            return False
    
    def logout(self) -> bool:
        """用户登出"""
        if not self.session_id:
            return True
        
        try:
            message = Protocol.encode_message(MessageType.LOGOUT, {}, self.session_id)
            self.socket.send(message)
            self.session_id = None
            self.user_info = None
            return True
        except Exception as e:
            print(f"登出失败: {e}")
            return False
    
    def execute_sql(self, sql: str) -> bool:
        """执行SQL语句"""
        if not self.session_id:
            print("请先登录")
            return False
        
        try:
            message = Protocol.encode_message(MessageType.SQL_QUERY, {"sql": sql}, self.session_id)
            self.socket.send(message)
            
            # 等待响应
            time.sleep(0.5)
            return True
        except Exception as e:
            print(f"执行SQL失败: {e}")
            # 尝试重新连接
            if not self.connected:
                print("连接已断开，尝试重新连接...")
                self.connect()
            return False
    
    def _receive_messages(self):
        """接收服务器消息的线程"""
        buffer = b""
        
        while self.running and self.connected:
            try:
                data = self.socket.recv(4096)
                if not data:
                    break
                
                buffer += data
                
                # 处理完整的消息
                while len(buffer) >= 4:
                    msg_length = int.from_bytes(buffer[:4], byteorder='big')
                    if len(buffer) < 4 + msg_length:
                        break
                    
                    message_data = buffer[:4 + msg_length]
                    buffer = buffer[4 + msg_length:]
                    
                    message = Protocol.decode_message(message_data)
                    if message:
                        self._handle_server_message(message)
            
            except Exception as e:
                if self.running:
                    print(f"接收消息时出错: {e}")
                break
    
    def _handle_server_message(self, message: Dict[str, Any]):
        """处理服务器消息"""
        msg_type = message.get("type")
        data = message.get("data", {})
        session_id = message.get("session_id")
        
        if msg_type == MessageType.RESPONSE.value:
            # 检查是否有嵌套的data结构
            actual_data = data.get("data", data) if "data" in data else data
            
            if actual_data.get("success"):
                # 处理成功响应
                if "user_info" in actual_data:  # 登录响应
                    self.session_id = session_id
                    self.user_info = actual_data["user_info"]
                    print(f"\n登录成功！欢迎 {self.user_info['username']}")
                    print(f"权限: {', '.join(self.user_info['permissions'])}")
                elif "columns" in actual_data:  # 查询结果
                    self._display_query_result(actual_data)
                else:  # 其他成功响应
                    print(f"\n操作成功: {actual_data.get('message', '')}")
                    if "affected_rows" in actual_data:
                        print(f"影响行数: {actual_data['affected_rows']}")
                    if "execution_time" in actual_data:
                        print(f"执行时间: {actual_data['execution_time']}")
            else:
                error_msg = actual_data.get('message') or actual_data.get('error', '未知错误')
                print(f"\n操作失败: {error_msg}")
        
        elif msg_type == MessageType.ERROR.value:
            error_code = data.get('error_code', 'UNKNOWN')
            error_message = data.get('error_message', '未知错误')
            print(f"\n错误 [{error_code}]: {error_message}")
        else:
            print(f"\n收到未知消息类型: {msg_type}")
    
    def _display_query_result(self, data: Dict[str, Any]):
        """显示查询结果"""
        columns = data.get("columns", [])
        rows = data.get("rows", [])
        row_count = data.get("row_count", 0)
        execution_time = data.get("execution_time", "N/A")
        
        print("\n查询结果:")
        print("-" * 80)
        
        if not rows:
            print("没有查询结果")
            return
        
        # 计算列宽
        col_widths = {}
        for col in columns:
            col_widths[col] = max(len(str(col)), 10)
        
        for row in rows:
            for col in columns:
                if col in row:
                    col_widths[col] = max(col_widths[col], len(str(row[col])))
        
        # 打印表头
        header = "|"
        for col in columns:
            header += f" {col:<{col_widths[col]}} |"
        print(header)
        
        # 打印分隔线
        separator = "|"
        for col in columns:
            separator += "-" * (col_widths[col] + 2) + "|"
        print(separator)
        
        # 打印数据行
        for row in rows:
            row_str = "|"
            for col in columns:
                value = str(row.get(col, ""))
                row_str += f" {value:<{col_widths[col]}} |"
            print(row_str)
        
        print("-" * 80)
        print(f"共 {row_count} 行，执行时间: {execution_time}")